/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.pa165.bookingmanager.dao.impl;

import cz.muni.fi.pa165.bookingmanager.entities.Reservation;
import cz.muni.fi.pa165.bookingmanager.exceptions.IllegalOrphanException;
import cz.muni.fi.pa165.bookingmanager.exceptions.NonexistentEntityException;
import cz.muni.fi.pa165.bookingmanager.exceptions.PreexistingEntityException;
import cz.muni.fi.pa165.bookingmanager.dao.ReservationManager;
import cz.muni.fi.pa165.bookingmanager.other.PaymentStatusEnum;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author Daniel Sák, 374560
 */
@Stateless
public class ReservationManagerImpl implements Serializable, ReservationManager {
    private static final long serialVersionUID = 1L;

    @PersistenceContext
    private EntityManager em;

    @Override
    public void createReservation(Reservation reservation) throws IllegalOrphanException, PreexistingEntityException {
        if (!isValidEntity(reservation)) {
            throw new IllegalArgumentException("Invalid Reservation entity");
        }
        if (reservation.getId() != null) {
            throw new IllegalOrphanException(null);
        }
        try {
            em.persist(reservation);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    @Override
    public void updateReservation(Reservation reservation) throws IllegalOrphanException, NonexistentEntityException {
        if (!isValidEntity(reservation)) {
            throw new IllegalArgumentException("Invalid Reservation entity");
        }
        if (reservation.getId() == null) {
            throw new IllegalOrphanException(null);
        }
        try {
            if (em.find(Reservation.class, reservation.getId()) == null) {
                throw new NonexistentEntityException("The reservation with id " + reservation.getId() + " no longer exists.");
            }
            em.merge(reservation);
        } catch (IllegalArgumentException ex) {
            throw new NonexistentEntityException("The Reservation entity no longer exists.", ex);
        }
    }

    @Override
    public void deleteReservation(Reservation reservation) throws IllegalOrphanException, NonexistentEntityException {
        if (!isValidEntity(reservation)) {
            throw new IllegalArgumentException("Invalid Reservation entity");
        }
        if (reservation.getId() == null) {
            throw new IllegalOrphanException(null);
        }
        try {
            em.remove(em.merge(reservation));
            //reservation.setId(null);
        } catch (IllegalArgumentException ex) {
            throw new NonexistentEntityException("The room entity no longer exists.", ex);
        }
    }

    @Override
    public Reservation getResevationByID(Long reservationID) {
        return em.find(Reservation.class, reservationID);
    }

    @Override
    public List<Reservation> findAllHotelReservations(Long hotelID) {
        Query query = em.createQuery("SELECT x FROM Reservation x WHERE x.hotel.id =" + hotelID);
        return query.getResultList();
    }

    @Override
    public List<Reservation> findAllRoomReservations(Long roomID) {
        Query query = em.createQuery("SELECT x FROM Reservation x WHERE x.room.id =" + roomID);
        return query.getResultList();
    }

    @Override
    public List<Reservation> findAllHotelReservations(Long hotelID, Date startDate) {
        Query query = em.createQuery("SELECT x FROM Reservation x WHERE x.hotel.id =" + hotelID + "AND x.startDate >= '" + startDate + "'");
        return query.getResultList();
    }

    @Override
    public List<Reservation> findAllRoomReservations(Long roomID, Date startDate) {
        Query query = em.createQuery("SELECT x FROM Reservation x WHERE x.room.id =" + roomID + "AND x.startDate >= '" + startDate + "'");
        return query.getResultList();
    }

    @Override
    public List<Reservation> findAllReservationsByPaid(PaymentStatusEnum paid) {
        final Query query = em.createQuery("SELECT object(x) FROM Reservation AS x WHERE x.paid= :paid");
        query.setParameter("paid", paid);
        return query.getResultList();
    }

    private boolean isValidEntity(Reservation reservation) {
        if (reservation == null) {
            return false;
        }

        if (reservation.getCustomers() == null) {
            return false;
        }

        if (reservation.getDuration() <= 0) {
            return false;
        }

        if (reservation.getHotel() == null) {
            return false;
        }

        if (reservation.getRoom() == null) {
            return false;
        }


        if (reservation.getStartDate() == null) {
            return false;
        }

        if (reservation.getTotalPrice() == null || reservation.getTotalPrice().compareTo(BigDecimal.ZERO) <= 0) {
            return false;
        }
        return true;
    }
}
